import { getFormByProcessId, startProcess, detail, completeTask, transferTask, delegateTask, rollbackTask, terminateProcess, addMultiInstance } from '@/api/plugin/workflow/process'

import Layout from '@/page/index/'
import defaultValues from './default-values'

import Print from '../util/print'

import { mapGetters } from 'vuex'

export default {
  mixins: [defaultValues],
  computed: {
    ...mapGetters(['tag', 'userInfo', 'permission']),
  },
  data() {
    return {
      process: {}, // 流程定义/流程实例信息
      buttonList: [], // 配置按钮信息
      flow: [], // 流转信息
      userSelectType: '', // 人员选择类型 transfer转办 delegate委托 copy抄送 assignee审核人
      checkType: 'radio', // 人员选择check类型 radio单选 checkbox多选
      comment: '', // 评论
      bpmnOption: {}, // 流程图配置信息
      watermarkText: '', //水印文字
      defaultChecked: '', // 人员选择默认选中
      waiting: true, // 骨架屏加载中
    }
  },
  mounted() {
    this.watermarkText = this.userInfo.user_name + " " + this.userInfo.real_name
  },
  methods: {
    // 动态路由跳转
    dynamicRoute(row, type, async = false) {
      const { id, taskId, processInstanceId, processId, formKey, formUrl } = row
      let param = Buffer.from(JSON.stringify({
        processId: id,
        taskId,
        processInsId: processInstanceId || processId
      })).toString('base64')

      if (formKey && formKey.startsWith('wf_ex_')) {
        if (formUrl) { // 配置了自定义路由
          this.$router.push(formUrl + `?p=${param}`)
        } else { // 动态添加路由
          this.$router.addRoutes([{
            path: `/workflow/process/external`,
            component: Layout,
            children: [{
              path: `${formKey.substring(6)}/${type}`,
              name: type == 'start' ? '发起流程' : '流程详情',
              component: () =>
                import( /* webpackChunkName: "views" */ `@/views/plugin/workflow/process/external/${formKey.substring(6)}/${type}.vue`),
            }]
          }])
          this.$router.push(`/workflow/process/external/${formKey.substring(6)}/${type}?p=${param}`)
        }
      } else {
        if (async) {
          return new Promise((resolve) => {
            resolve({ row, type, param })
          })
        } else {
          this.$router.push(`/workflow/process/${type}/${param}`)
        }
      }
    },
    // 根据可读可写，过滤avue column
    filterAvueColumn(column, taskForm, props = { label: 'label', prop: 'prop' }) {
      const _this = this

      if (!column || column.length == 0) return { column, vars: [] }

      const values = []
      const vars = []
      column.forEach(col => {
        let c = taskForm.find(s => s.id == col[props.prop])
        if (c && c.readable) {
          if (c.writable) { // 可写，记录需要提交的字段、处理字段默认值
            vars.push(col[props.prop])
            if (col.value) col.value = _this.getDefaultValues(col.value)
          } else { // 不可写，清除校验与默认值
            if (col.type == 'dynamic') {
              col.children.addBtn = false
              col.children.delBtn = false
            } else {
              col.readonly = true
              col.disabled = true
            }
            delete col.rules
            delete col.value
          }
          if (col.type == 'dynamic') { // 处理子表单
            col.children.column = _this.filterAvueColumn(col.children.column, taskForm).column
          }
          if (col.rules && col.pattern) { // 处理正则
            col.rules.forEach(c => {
              if (c.pattern) c.pattern = new RegExp(col.pattern)
            })
          }

          // 处理事件
          let event = ['change', 'blur', 'click', 'focus']
          event.forEach(e => {
            if (col[e]) col[e] = eval((col[e] + '').replace(/this/g, '_this'))
          })
          if (col.event) Object.keys(col.event).forEach(key => col.event[key] = eval((col.event[key] + '').replace(/this/g, '_this')))

          values.push(col)
        }
      })
      return { column: values, vars }
    },
    /**
     * 获取流程发起表单
     * @param processId 流程定义id
     * @returns Promise({"process": "流程定义信息", "startForm": "开始节点表单"})
     */
    getStartForm(processId) {
      return new Promise((resolve, reject) => {
        getFormByProcessId({ processId }).then(res => {
          const { process } = res.data.data
          process.hideComment = true
          this.process = process
          this.tag.label = '发起流程 - ' + process.name
          resolve(res.data.data)
        }).catch(() => {
          reject()
        })
      })
    },
    /**
     * 发起流程
     * @param form {"processId": "流程定义id", ...表单自定义字段变量}
     */
    handleStartProcess(form) {
      if (this.$refs.examineForm && this.$refs.examineForm.examineForm) {
        const { copyUser, assignee } = this.$refs.examineForm.examineForm
        form = { ...form, copyUser, assignee }
      }
      return new Promise((resolve, reject) => {
        startProcess(form).then(() => {
          resolve()
        }).catch(() => {
          reject()
        })
      })
    },
    /**
     * 获取流程任务详情
     * @param taskId 任务id
     * @param processInsId 流程实例id
     * @returns Promise({"process": "流程实例信息", "form": "表单信息", "flow": "流转信息", "button": "配置按钮信息", "bpmnOption": "流程图配置"})
     */
    getTaskDetail(taskId, processInsId) {
      return new Promise((resolve, reject) => {
        detail({ taskId, processInsId }).then(res => {
          const { process, form, flow, button } = res.data.data
          const { xml } = process

          const bpmnOption = {
            mode: 'view', xml,
            flows: this.handleResolveFlows(flow)
          }
          this.process = process
          this.flow = flow
          this.buttonList = button
          this.bpmnOption = bpmnOption
          this.tag.label = '流程详情 - ' + process.processDefinitionName
          resolve({ process, form, flow, button, bpmnOption })
        }).catch(() => {
          reject()
        })
      })
    },
    /**
     * 任务审核
     * @param pass 驳回/通过
     */
    handleCompleteTask(pass, variables) {
      return new Promise((resolve, reject) => {
        const { comment, copyUser, assignee } = this.$refs.examineForm.examineForm
        if (!pass && !comment) {
          this.$message.error("请填写批复意见")
          this.submitLoading = false
          reject()
          return
        }
        const { taskId, processInstanceId, processDefinitionName, processDefinitionId } = this.process
        const param = {
          taskId, processInstanceId, processDefinitionName, processDefinitionId, pass,
          comment, copyUser, assignee, variables
        }
        completeTask(param).then(() => {
          resolve()
        }).catch(() => {
          reject()
        })
      })
    },
    /**
     * 驳回到指定节点
     * @param nodeId 节点id
     */
    handleRollbackTask(nodeId) {
      const { taskId } = this.process
      rollbackTask({ comment: this.comment, nodeId, taskId }).then(() => {
        this.$message.success("回退成功")
        this.handleCloseTag('/plugin/workflow/process/todo')
      })
    },
    /**
     * 终止流程
     */
    handleTerminateProcess() {
      const comment = this.comment
      if (!comment) {
        this.$message.error("请填写批复意见")
        return
      }
      this.$confirm('确定要终止此流程吗?', '警告', {
        type: 'warning'
      }).then(() => {
        const { taskId } = this.process

        terminateProcess({ taskId, comment }).then(() => {
          this.$message.success("操作成功")
          this.handleCloseTag('/plugin/workflow/process/todo')
        })
      }).catch(() => {

      })
    },
    // 人员选择弹窗
    handleUserSelect({ type, checkType }) {
      if (!this.comment && ['transfer', 'delegate'].includes(type)) {
        this.$message.error("请填写批复意见")
        return
      }
      if (type == 'assignee') this.defaultChecked = this.$refs.examineForm.examineForm.assignee
      else if (type == 'copy') this.defaultChecked = this.$refs.examineForm.examineForm.copyUser

      this.$refs['user-select'].visible = true
      this.userSelectType = type
      this.checkType = checkType
    },
    // 选人回调
    handleUserSelectConfirm(id, name) {
      const { comment, copyUser } = this.$refs.examineForm.examineForm
      const { taskId, processInstanceId, processDefinitionName, processDefinitionId } = this.process

      const type = this.userSelectType
      const param = {
        taskId, processInstanceId, processDefinitionName, processDefinitionId,
        assignee: id,
        comment, copyUser
      }
      if (type == 'transfer') {
        transferTask(param).then(() => { // 转办
          this.$message.success("转办成功")
          this.handleCloseTag('/plugin/workflow/process/todo')
        })
      } else if (type == 'delegate') { // 委托
        delegateTask(param).then(() => {
          this.$message.success("委托成功")
          this.handleCloseTag('/plugin/workflow/process/todo')
        })
      } else if (type == 'addInstance') { // 加签
        addMultiInstance(param).then(() => {
          this.$message.success("加签成功")
        })
      } else if (type == 'copy') { // 抄送
        this.$refs.examineForm.examineForm.copyUser = id
        this.$refs.examineForm.examineForm.$copyUser = name
      } else if (type == 'assignee') { // 指定下一步审批人
        this.$refs.examineForm.examineForm.assignee = id
        this.$refs.examineForm.examineForm.$assignee = name
      }
      this.$refs['user-select'].visible = false
    },
    handlePrint() { //打印
      // this.watermark({ text: this.watermarkText })
      Print(this.$refs.printBody)
    },
    // 关闭当前tag，并跳转
    handleCloseTag(path) {
      this.$store.commit('DEL_TAG', this.tag)
      if (path) this.$router.push(path)
    },
    handleResolveFlows(flow) {
      const flows = []
      flow.forEach(f => {
        const { assigneeName, createTime, comments } = f
        const ff = {
          id: f.historyActivityId,
        }
        let tooltip = ''
        if (assigneeName) {
          tooltip = `<span title='${assigneeName}'>${assigneeName}</span><br>`
          if (createTime) tooltip += `<span title='${createTime}'>${this.dateFormat(new Date(createTime), 'yyyy-MM-dd hh:mm')}</span><br>`

          if (comments && comments.length > 0) {
            let comment
            let { type, fullMessage } = comments[0]

            if (type == 'assigneeComment') {
              comment = '变更审核人：' + fullMessage
              ff.class = 'nodeWarn'
            }
            if (type == 'dispatchComment') {
              comment = '调度：' + fullMessage
              ff.class = 'nodeWarn'
            }
            if (type == 'transferComment') {
              comment = '转办：' + fullMessage
              ff.class = 'nodeWarn'
            }
            if (type == 'delegateComment') {
              comment = '委托：' + fullMessage
              ff.class = 'nodeWarn'
            }
            if (type == 'rollbackComment') {
              comment = '驳回：' + fullMessage
              ff.class = 'nodeError'
            }
            if (type == 'terminateComment') {
              comment = '终止：' + fullMessage
              ff.class = 'nodeError'
            }
            if (type == 'addMultiInstanceComment') {
              comment = '加签：' + fullMessage
              ff.class = 'nodeWarn'
            }
            if (type == 'deleteMultiInstanceComment') {
              comment = '减签：' + fullMessage
              ff.class = 'nodeError'
            }
            if (type == 'comment') {
              comment = '审批：' + fullMessage
              ff.class = 'nodeSuccess'
            }
            tooltip += `<span title='${comment}'>${comment}</span>`
          }
          ff.tooltip = tooltip
        }

        if (f.historyActivityType == 'sequenceFlow') ff.class = 'lineWarn'
        else if (!ff.class && f.historyActivityType != 'candidate') ff.class = 'nodeSuccess'

        const index = flows.findIndex(fl => fl.id == f.historyActivityId)
        if (index != -1) flows.splice(index, 1, ff)
        else flows.push(ff)
      })
      return flows
    },
    // 上传组件预览
    handleUploadPreview(file, column, done) {
      const { url } = file
      const { video, img } = this.$typeList
      if (video.test(url) || img.test(url)) done()
      else window.open(url)
    },
  }
}